﻿/*
 * address.cpp
 *
 *  Created on: 2017年2月10日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_OS_COM DM_API_EXPORT

#include <dm/os/com/address.hpp>
#include <dm/os/log/logger.hpp>

namespace dm{
namespace os{
namespace com{

static const char* headers[CAddress::Unknow+1] ={
		"SRP",	// Serial Port
		"TCL",	// Tcp Client
		"TBC",	// Tcp bind client
		"TSR",	// TCP server
		"TCC",	// TCP connect
		"UCL",	// UDP Client
		"UBC",	// UDP bind client
		"USR",	// UDP Server
		"UCC",	// UDP Connect
		"CAN",	// CAN network
		"UNK"		// Unknow
};

static const char* logModule = "CAddress.com.os.dm";

const char* CAddress::typeString( const EType& t ){
	if( t<CAddress::SerialPort || t>=CAddress::Unknow )
		return headers[CAddress::Unknow];
	return headers[t];
}

CAddress::CAddress():m_type(Unknow),m_addr(0){
	log().debug(THISMODULE "创建对象");
}

CAddress::CAddress( const CAddress& addr ):CAddr(),m_type(addr.m_type){
	switch( m_type ){
	case SerialPort:
		log().debug( THISMODULE "由SerialPort设备创建");
		m_addr = new CSerialAddr((*(CSerialAddr*)addr.m_addr));
		break;
	case TcpClient:
		log().debug( THISMODULE "由TcpClient设备创建");
		m_addr = new CTcpClientAddr(*(CTcpClientAddr*)addr.m_addr);
		break;
	case TcpBindClient:
		log().debug( THISMODULE "由TcpBindClient设备创建");
		m_addr = new CTcpBindClientAddr(*(CTcpBindClientAddr*)addr.m_addr);
		break;
	case TcpServer:
		log().debug( THISMODULE "由TcpServer设备创建");
		m_addr = new CTcpServerAddr(*(CTcpServerAddr*)addr.m_addr);
		break;
	case UdpClient:
		log().debug( THISMODULE "由UdpClient设备创建");
		m_addr = new CUdpClientAddr(*(CUdpClientAddr*)addr.m_addr);
		break;
	case UdpBindClient:
		log().debug( THISMODULE "由UdpBindClient设备创建");
		m_addr = new CUdpBindClientAddr(*(CUdpBindClientAddr*)addr.m_addr);
		break;
	case UdpServer:
		log().debug( THISMODULE "由UdpServer设备创建");
		m_addr = new CUdpServerAddr(*(CUdpServerAddr*)addr.m_addr);
		break;
	case Can:
		log().debug( THISMODULE "由CAN设备创建");
		m_addr = new CCanAddr(*(CCanAddr*)addr.m_addr);
		break;
	default:
		log().warnning( THISMODULE "未知设备类型");
		m_addr = 0;
	}
}

CAddress::CAddress( const CSerialAddr& addr ):m_type(SerialPort),m_addr(new CSerialAddr(addr)){
	log().debug( THISMODULE "由CSerialAddr设备构建");
}

CAddress::CAddress( const CTcpClientAddr& addr ):m_type(TcpClient),m_addr(new CTcpClientAddr(addr)){
	log().debug( THISMODULE "由CTcpClientAddr设备构建");
}

CAddress::CAddress( const CTcpBindClientAddr& addr ):m_type(TcpBindClient),m_addr(new CTcpBindClientAddr(addr)){
	log().debug( THISMODULE "由CTcpBindClientAddr设备构建");
}

CAddress::CAddress( const CTcpServerAddr& addr ):m_type(TcpServer),m_addr(new CTcpServerAddr(addr)){
	log().debug( THISMODULE "由CTcpServerAddr设备构建");
}

CAddress::CAddress( const CTcpConnectAddr& addr ):m_type(TcpConnect),m_addr(new CTcpConnectAddr(addr)){
	log().debug( THISMODULE "由CTcpConnectAddr设备构建");
}

CAddress::CAddress( const CUdpClientAddr& addr ):m_type(UdpClient),m_addr(new CUdpClientAddr(addr)){
	log().debug( THISMODULE "由CUdpClientAddr设备构建");
}

CAddress::CAddress( const CUdpBindClientAddr& addr ):m_type(UdpBindClient),m_addr(new CUdpBindClientAddr(addr)){
	log().debug( THISMODULE "由CUdpBindClientAddr设备构建");
}

CAddress::CAddress( const CUdpServerAddr& addr ):m_type(UdpServer),m_addr(new CUdpServerAddr(addr)){
	log().debug( THISMODULE "由CUdpServerAddr设备构建");
}

CAddress::CAddress( const CCanAddr& addr ):m_type(Can),m_addr(new CCanAddr(addr)){
	log().debug( THISMODULE "由CCanAddr设备构建");
}

CAddress::~CAddress(){
	if( m_addr!=0 ){
		log().debug( THISMODULE "销毁对象%s",m_addr->toString().c_str());
		delete m_addr;
	}
}

CAddress& CAddress::operator =( const CAddress& addr ){
	reset();
	m_type = addr.m_type;
	switch( m_type ){
	case SerialPort:
		log().debug( THISMODULE "由SerialPort赋值");
		m_addr = new CSerialAddr((*(CSerialAddr*)addr.m_addr));
		break;
	case TcpClient:
		log().debug( THISMODULE "由TcpClient赋值");
		m_addr = new CTcpClientAddr(*(CTcpClientAddr*)addr.m_addr);
		break;
	case TcpBindClient:
		log().debug( THISMODULE "由TcpBindClient赋值");
		m_addr = new CTcpBindClientAddr(*(CTcpBindClientAddr*)addr.m_addr);
		break;
	case TcpServer:
		log().debug( THISMODULE "由TcpServer赋值");
		m_addr = new CTcpServerAddr(*(CTcpServerAddr*)addr.m_addr);
		break;
	case TcpConnect:
		log().debug( THISMODULE "由TcpConnect赋值");
		m_addr = new CTcpConnectAddr(*(CTcpConnectAddr*)addr.m_addr);
		break;
	case UdpClient:
		log().debug( THISMODULE "由UdpClient赋值");
		m_addr = new CUdpClientAddr(*(CUdpClientAddr*)addr.m_addr);
		break;
	case UdpBindClient:
		log().debug( THISMODULE "由UdpBindClient赋值");
		m_addr = new CUdpBindClientAddr(*(CUdpBindClientAddr*)addr.m_addr);
		break;
	case UdpServer:
		log().debug( THISMODULE "由UdpServer赋值");
		m_addr = new CUdpServerAddr(*(CUdpServerAddr*)addr.m_addr);
		break;
	case Can:
		log().debug( THISMODULE "由Can赋值");
		m_addr = new CCanAddr(*(CCanAddr*)addr.m_addr);
		break;
	default:
		log().debug( THISMODULE "未知类型的赋值");
		m_addr = 0;
	}

	return *this;
}

CAddress& CAddress::operator =( const CSerialAddr& addr ){
	reset();

	log().debug( THISMODULE "由CSerialAddr赋值");

	m_type = SerialPort;
	m_addr = new CSerialAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CTcpClientAddr& addr ){
	reset();

	log().debug( THISMODULE "由CTcpClientAddr赋值");

	m_type = TcpClient;
	m_addr = new CTcpClientAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CTcpBindClientAddr& addr ){
	reset();

	log().debug( THISMODULE "由CTcpBindClientAddr赋值");

	m_type = TcpBindClient;
	m_addr = new CTcpBindClientAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CTcpServerAddr& addr ){
	reset();

	log().debug( THISMODULE "由CTcpServerAddr赋值");

	m_type = TcpServer;
	m_addr = new CTcpServerAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CTcpConnectAddr& addr ){
	reset();

	log().debug( THISMODULE "由CTcpConnectAddr赋值");

	m_type = TcpConnect;
	m_addr = new CTcpConnectAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CUdpClientAddr& addr ){
	reset();

	log().debug( THISMODULE "由CUdpClientAddr赋值");

	m_type = UdpClient;
	m_addr = new CUdpClientAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CUdpBindClientAddr& addr ){
	reset();

	log().debug( THISMODULE "由CUdpBindClientAddr赋值");

	m_type = UdpBindClient;
	m_addr = new CUdpBindClientAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CUdpServerAddr& addr ){
	reset();

	log().debug( THISMODULE "由CUdpServerAddr赋值");

	m_type = UdpServer;
	m_addr = new CUdpServerAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CUdpConnectAddr& addr ){
	reset();

	log().debug( THISMODULE "由CUdpConnectAddr赋值");

	m_type = UdpConnect;
	m_addr = new CUdpConnectAddr(addr);

	return *this;
}

CAddress& CAddress::operator =( const CCanAddr& addr ){
	reset();

	log().debug( THISMODULE "由CCanAddr赋值");

	m_type = Can;
	m_addr = new CCanAddr(addr);

	return *this;
}

template<typename T>
inline static bool compare( const void* p1,const void* p2 ){
	return (*((T*)(p1)))==(*((T*)(p2)));
}

bool CAddress::operator ==( const CAddress& addr )const{
	if( m_type!=addr.m_type ){
		switch( m_type ){
		case SerialPort:
			return compare<CSerialAddr>(m_addr,addr.m_addr);
			break;
		case TcpClient:
			return compare<CTcpClientAddr>(m_addr,addr.m_addr);
			break;
		case TcpBindClient:
			return compare<CTcpBindClientAddr>(m_addr,addr.m_addr);
			break;
		case TcpServer:
			return compare<CTcpServerAddr>(m_addr,addr.m_addr);
			break;
		case TcpConnect:
			return compare<CTcpConnectAddr>(m_addr,addr.m_addr);
			break;
		case UdpClient:
			return compare<CUdpClientAddr>(m_addr,addr.m_addr);
			break;
		case UdpBindClient:
			return compare<CUdpBindClientAddr>(m_addr,addr.m_addr);
			break;
		case UdpServer:
			return compare<CUdpServerAddr>(m_addr,addr.m_addr);
			break;
		case Can:
			return compare<CCanAddr>(m_addr,addr.m_addr);
			break;
		default:
			return false;
		}
	}
	return false;
}

const CSerialAddr* CAddress::asSerialPort()const{
	return as<CSerialAddr>(SerialPort);
}

const CTcpClientAddr* CAddress::asTcpClient()const{
	return as<CTcpClientAddr>(TcpClient);
}

const CTcpBindClientAddr* CAddress::asTcpBindClient()const{
	return as<CTcpBindClientAddr>(TcpBindClient);
}

const CTcpServerAddr* CAddress::asTcpServer()const{
	return as<CTcpServerAddr>(TcpServer);
}

const CTcpConnectAddr* CAddress::asTcpConnect()const{
	return as<CTcpConnectAddr>(TcpConnect);
}

const CUdpClientAddr* CAddress::asUdpClient()const{
	return as<CUdpClientAddr>(UdpClient);
}

const CUdpBindClientAddr* CAddress::asUdpBindClient()const{
	return as<CUdpBindClientAddr>(UdpBindClient);
}

const CUdpServerAddr* CAddress::asUdpServer()const{
	return as<CUdpServerAddr>(UdpServer);
}

const CUdpConnectAddr* CAddress::asUdpConnect()const{
	return as<CUdpConnectAddr>(UdpConnect);
}

const CCanAddr* CAddress::asCan()const{
	return as<CCanAddr>(Can);
}

bool CAddress::set( const EType& ,const char*  ){
	reset();
	return false;
}

void CAddress::reset(){
	if( m_addr!=0 )
		delete m_addr;
	m_type = Unknow;
	m_addr = 0;
}

void CAddress::output( std::ostream& ostr )const{
	ostr<<typeName()<<'#';
	switch( m_type ){
	case SerialPort:
		((const CSerialAddr*)(m_addr))->output(ostr);
		break;
	case TcpClient:
		((const CTcpClientAddr*)(m_addr))->output(ostr);
		break;
	case TcpServer:
		((const CTcpServerAddr*)(m_addr))->output(ostr);
		break;
	case TcpBindClient:
		((const CTcpBindClientAddr*)(m_addr))->output(ostr);
		break;
	case TcpConnect:
		((const CTcpConnectAddr*)(m_addr))->output(ostr);
		break;
	case UdpClient:
		((const CUdpClientAddr*)(m_addr))->output(ostr);
		break;
	case UdpServer:
		((const CUdpServerAddr*)(m_addr))->output(ostr);
		break;
	case UdpBindClient:
		((const CUdpBindClientAddr*)(m_addr))->output(ostr);
		break;
	case UdpConnect:
		((const CUdpConnectAddr*)(m_addr))->output(ostr);
		break;
	case Can:
		((const CCanAddr*)(m_addr))->output(ostr);
		break;
	default:
		break;
	}
}

template<typename T>
bool getStringAddr( CAddr** addr,CAddress::EType& type,
		const CAddress::EType& t,const char* buf,const int& len,const char* header ){
	if( std::strncmp(buf,header,3)==0 ){
		CAddr* a = new T;
		if( a->fromString(buf+4,len-4) ){
			type = t;
			*addr = a;
			return true;
		}
		delete a;
	}
	return false;
}

bool CAddress::fromString( const char* buf,const int& l ){
	int len = l;
	if( len==0 )
		len = (int)std::strlen(buf);

	if( len<4 )
		return false;
	if( buf[3]!='#')
		return false;
	reset();

	if( getStringAddr<CSerialAddr>(&m_addr,m_type,SerialPort,buf,len,headers[SerialPort]) )
		return true;
	else if( getStringAddr<CTcpClientAddr>(&m_addr,m_type,TcpClient,buf,len,headers[TcpClient]) )
		return true;
	else if( getStringAddr<CTcpServerAddr>(&m_addr,m_type,TcpServer,buf,len,headers[TcpBindClient]) )
		return true;
	else if( getStringAddr<CTcpBindClientAddr>(&m_addr,m_type,TcpBindClient,buf,len,headers[TcpBindClient]) )
		return true;
	else if( getStringAddr<CTcpConnectAddr>(&m_addr,m_type,TcpConnect,buf,len,headers[TcpConnect]) )
		return true;
	else if( getStringAddr<CUdpClientAddr>(&m_addr,m_type,UdpClient,buf,len,headers[UdpClient]) )
		return true;
	else if( getStringAddr<CUdpServerAddr>(&m_addr,m_type,UdpServer,buf,len,headers[UdpServer]) )
		return true;
	else if( getStringAddr<CUdpBindClientAddr>(&m_addr,m_type,UdpBindClient,buf,len,headers[UdpBindClient]) )
		return true;
	else if( getStringAddr<CUdpConnectAddr>(&m_addr,m_type,UdpConnect,buf,len,headers[UdpConnect]) )
		return true;
	else if( getStringAddr<CCanAddr>(&m_addr,m_type,Can,buf,len,headers[Can]) )
		return true;
	else
		return false;
}

bool CAddress::fromStringList( const dm::string::CStringList& ){
	return false;
}
}
}
}
